package com.gitee.wsl.compose.chart.sample

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.absolutePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.unit.dp
import com.gitee.wsl.compose.chart.ChartAdapter
import com.gitee.wsl.compose.chart.ChartLayout
import com.gitee.wsl.compose.chart.ExperimentalKoalaPlotApi
import com.gitee.wsl.compose.chart.SelectChangedListener
import com.gitee.wsl.compose.chart.SelectCheck

import com.gitee.wsl.compose.chart.generateHueColorPalette
import com.gitee.wsl.compose.chart.legend.Flow
import com.gitee.wsl.compose.chart.legend.Legend
import com.gitee.wsl.compose.chart.legend.LegendLocation
import com.gitee.wsl.compose.chart.xy.XYGraph
import com.gitee.wsl.compose.chart.xy.axis.model.CategoryAxisModel
import com.gitee.wsl.compose.chart.xy.axis.model.FloatLinearAxisModel
import com.gitee.wsl.compose.chart.xy.bar.DefaultBar
import com.gitee.wsl.compose.chart.xy.bar.group.GroupedVerticalBarPlot
import com.gitee.wsl.compose.chart.xy.bar.model.GroupedBarEntry
import com.gitee.wsl.compose.chart.xy.bar.group.model.groupedBar

import com.gitee.wsl.compose.modifier.layout.VerticalRotation
import com.gitee.wsl.compose.modifier.layout.rotateVertically
import com.gitee.wsl.compose.ui.widget.Symbol
import com.gitee.wsl.compose.modifier.layout
import com.gitee.wsl.ext.number.toString

import kotlin.math.ceil

private val colors = generateHueColorPalette(PopulationData.Categories.entries.size)

private fun barChartEntries(): List<GroupedBarEntry<Int, Float>> {
    return ChartAdapter.Companion.groupedBar {
        PopulationData.years.mapIndexed { yearIndex, year ->
            PopulationData.Categories.entries.forEachIndexed { index, categories ->
                val y = PopulationData.data[PopulationData.Categories.entries[index]]!![yearIndex].toFloat()
                grouped(year,0f,y)
            }
        }
    }

//    return PopulationData.years.mapIndexed { yearIndex, year ->
//        object : VerticalBarPlotGroupedPointEntry<Int, Float> {
//            override val x: Int = year
//
//            override val y: List<VerticalBarPosition<Float>> = object : AbstractList<VerticalBarPosition<Float>>() {
//                override val size: Int
//                    get() = PopulationData.Categories.entries.size
//
//                override fun get(index: Int): VerticalBarPosition<Float> {
//                    return VerticalBarPosition(
//                        0f,
//                        PopulationData.data[PopulationData.Categories.entries[index]]!![yearIndex].toFloat()
//                    )
//                }
//            }
//        }
//    }
}

@OptIn(ExperimentalKoalaPlotApi::class)
@Composable
private fun LegendView(thumbnail: Boolean = false,selectCheck: SelectCheck,selectChangedListener: SelectChangedListener?) {
    if (!thumbnail) {
        Legend.Flow(
            itemCount = PopulationData.Categories.entries.size,
            symbol = { i,selected ->
                Symbol(modifier = Modifier.size(padding), fillBrush = SolidColor(colors[i]))
            },
            label = { i,selected,listener ->
                Text(PopulationData.Categories.entries[i].toString())
            },
            selectCheck = selectCheck,
            selectChangedListener = selectChangedListener
        )
    }
}

@OptIn(ExperimentalKoalaPlotApi::class)
val groupedVerticalBarSampleView = object : SampleView {
    override val name: String = "Grouped Vertical Bar"

    override val thumbnail = @Composable {
        ThumbnailTheme {
            BarSample2Plot(true, name)
        }
    }

    override val content: @Composable () -> Unit = @Composable {
        Column {
            ChartLayout(
                modifier = Modifier.sizeIn(minHeight = 200.dp, maxHeight = 600.dp).weight(1f)
            ) {
                BarSample2Plot(false, "New York City Population")
            }
        }
    }
}

private const val PopulationScale = 1E6f

@OptIn(ExperimentalKoalaPlotApi::class)
@Composable
private fun BarSample2Plot(thumbnail: Boolean, title: String) {
    val barChartEntries: List<GroupedBarEntry<Int, Float>> = remember(thumbnail) { barChartEntries() }

    ChartLayout(
        modifier = paddingMod,
        title = { ChartTitle(title) },
        legend = {selected,listener-> LegendView(thumbnail,selected,listener) },
        legendLocation = LegendLocation.BOTTOM
    ) {
        XYGraph(
            xAxisModel = CategoryAxisModel(PopulationData.years),
            yAxisModel = FloatLinearAxisModel(
                0f..(ceil(PopulationData.maxPopulation / PopulationScale) * PopulationScale),
                minorTickCount = 0
            ),
            content = {
                GroupedVerticalBarPlot(
                    data = barChartEntries,
                    bar = { dataIndex, groupIndex, _ ->
                        DefaultBar(
                            brush = SolidColor(colors[groupIndex]),
                            modifier = Modifier.sizeIn(minWidth = 5.dp, maxWidth = 20.dp),
                        ) {
                            if (!thumbnail) {
                                val borough = PopulationData.Categories.entries[groupIndex]
                                val pop = PopulationData.data[borough]!![dataIndex]
                                HoverSurface { Text("$borough: $pop") }
                            }
                        }
                    }
                )
            },
            xAxisLabels = {
                if (!thumbnail) AxisLabel("$it", Modifier.padding(top = 2.dp))
            },
            xAxisTitle = {
                if (!thumbnail) AxisTitle("Year")
            },
            yAxisLabels = {
                if (!thumbnail) {
                    AxisLabel(
                        (it / PopulationScale).toString(2),
                        Modifier.absolutePadding(right = 2.dp)
                    )
                }
            },
            yAxisTitle = {
                if (!thumbnail) {
                    Text(
                        "Population (Millions)",
                        color = MaterialTheme.colorScheme.onBackground,
                        style = MaterialTheme.typography.titleMedium,
                        modifier = Modifier
                            .layout {
                                rotateVertically(VerticalRotation.COUNTER_CLOCKWISE)
                            }
                            .padding(bottom = padding),
                    )
                }
            },
            verticalMajorGridLineStyle = null
        )
    }
}
